export class Utils {
	/** 获取数据类型
	 * @param {any} any
	 * @returns {String}
	 */
	static getType(any) {
		const result = Object.prototype.toString.call(any).replace(/(^\[object\s)(\w+)(]$)/, function (_$0, _$1,
			$2) {
			return $2.toLowerCase();
		});
		return result;
	}
	/** 
	 * isBoolean
	 * @param {any} x
	 * @returns {Boolean}
	 */
	static isBoolean = (x) => {
		return Utils.getType(x) === 'boolean';
	}
	/** 
	 * isString 
	 * */
	static isString = (x) => {
		return Utils.getType(x) === 'string';
	}
	/**
	 * isArray
	 */
	static isArray = (x) => {
		return Array.isArray(x);
	}
	/** 
	 * isObject
	 * */
	static isObject = (x) => {
		return Utils.getType(x) === 'object';
	}
	/** 
	 * isFunction
	 * */
	static isFunction = (x) => {
		return typeof x === 'function';
	}
	/**
	 * isNumber
	 * */
	static isNumber = (x) => {
		return typeof x === 'number';
	}
	/**
	 * isUndefined
	 * */
	static isUndefined = (x) => {
		return typeof x === 'undefined';
	}
	/**
	 * isNotUndefined
	 * */
	static isNotUndefined = (x) => {
		return !Utils.isUndefined(x);
	}
	/** 
	 * isNullObject 是否为空对象 空：false 非空：true 
	 * */
	static isNotNullObject = (x) => {
		let result = false;
		let count = 0;
		if (Utils.isObject(x)) {
			for (const o in x) {
				if (x.hasOwnProperty(o)) {
					count++;
				}
			}
			result = !!count;
		} else {
			result = false;
		}
		return result;
	}
	static isNullObject = (x) => {
		return !Utils.isNotNullObject(x);
	}
	/**
	 * isNull
	 * */
	static isNull = (x) => {
		return Utils.getType(x) === 'null';
	}
	/** 
	 * 是否为空数据
	 * */
	static isEmpty = (value) => {
		if (Utils.isObject(value) && Object.keys(value).length === 0) {
			return true;
		}
		if (Utils.isArray(value) && value.length === 0) {
			return true;
		}
		if (Utils.isString(value) && value.trim() === '') {
			return true;
		}
		if (Utils.isUndefined(value)) {
			return true;
		}
		if (Utils.isNull(value)) {
			return true;
		}
		return false;
	}
	static isNotEmpty = (value) => {
		return !Utils.isEmpty(value);
	}
	/** 
	 * 一个字符串是否符合数字的模式 
	 * */
	static isNumericString = (value) => {
		return /^\d+(\.\d+)?$/.test(value);
	}

	/**
	 * 是否存在有效属性
	 */
	static isValidKey = (key, object) => {
		return key in object;
	}

	/**
	 * 取随机数
	 * n:返回随机数个数
	 * @param {Number} n
	 * @returns {String}
	 */
	static getRandomChars = (n) => {
		let result = '';
		const numberChars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
		const lowerChars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
			'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
		];
		const upperChars = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
			'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
		];
		// const markChars = ['~', '!', '@', '#', '$', '%', '^', '*', '_', '+'];
		const tempChars = [...lowerChars, ...numberChars, ...upperChars];

		for (let i = 0; i < n; i++) {
			const id = Math.ceil(Math.random() * (tempChars.length - 1));
			result += tempChars[id];
		}

		return result;
	}

	/** 
	 * 计算字符串长度（包含中文，中文=2个长度） 
	 * @param {String} str
	 * @returns {Number}
	 * */
	static countStringLength = (str) => {
		const chineseRegex = /[\u4e00-\u9fa5]/;
		const arr = Array.from(str);
		let len = 0;
		arr.forEach(char => {
			if (chineseRegex.test(char)) {
				len = len + 2;
			} else {
				len = len + 1;
			}
		});
		return len;
	}
	/** 克隆 */
	static clone(obj) {
		let result = undefined;
		if (Utils.getType(obj) === 'object') {
			result = {};
		} else if (Utils.getType(obj) === 'array') {
			result = [];
		} else {
			result = obj;
		}
		for (const key in obj) {
			if (Utils.getType(obj[key]) === 'object') {
				result[key] = Utils.clone(obj[key]);
			} else if (Utils.getType(obj[key]) === 'array') {
				result[key] = Utils.clone(obj[key]);
			} else {
				result[key] = obj[key];
			}
		}
		return result;
	}

	/**
	 * jQuery param {a:1, b:2} => ?a=1&b=2
	 * @param {Object} a
	 * @returns {String}
	 */
	static param = (a) => {
		const s = [];
		const add = function (k, v) {
			v = typeof v === 'function' ? v() : v;
			v = v === null ? '' : v === undefined ? '' : v;
			s[s.length] = encodeURIComponent(k) + '=' + encodeURIComponent(v);
		};
		const buildParams = function (prefix, obj) {
			if (prefix) {
				if (Array.isArray(obj)) {
					for (let i = 0, len = obj.length; i < len; i++) {
						buildParams(
							prefix + '[' + (typeof obj[i] === 'object' && obj[i] ? i : '') + ']',
							obj[i]
						);
					}
				} else if (String(obj) === '[object Object]') {
					for (const key in obj) {
						buildParams(prefix + '[' + key + ']', obj[key]);
					}
				} else {
					add(prefix, obj);
				}
			} else if (Array.isArray(obj)) {
				for (let i = 0, len = obj.length; i < len; i++) {
					add(obj[i].name, obj[i].value);
				}
			} else {
				for (const key in obj) {
					buildParams(key, obj[key]);
				}
			}
			return s;
		};
		return buildParams('', a).join('&');
	}


	/**
	 * 提取字符串中的参数 xxxxx?a=1b=2 => {a: '1', b: '2'}
	 * @param {String} str
	 * @returns {Object}
	 */
	static getStrParam = (str) => {
		const regex = /[?&]([^=#]+)=([^&#]*)/g;
		let params = {};
		let match;
		while ((match = regex.exec(str)) !== null) {
			const key = (match[1]); // 参数名
			const value = (match[2]); // 参数值
			params[key] = value;
		}
		return params;
	}

	/**
	 * @description 一位数字 转换 两位数字 1 => 01
	 * @author da
	 * @param {number} n
	 * @returns {String}
	 */
	static to2digit(n) {
		return ('00' + n).slice(-2);
	}

	/**
	 * 等
	 * @param delay 毫秒
	 * @returns
	 */
	static sleep = (delay) => {
		return new Promise(resolve => setTimeout(resolve, delay));
	}

	/**
	 * 数字四舍五入 
	 * @param {String|Number}
	 * @returns {String}
	 */
	static toFixed = (num, n = 2) => {
		const strNum = num + '';
		let result = strNum;
		const reg = new RegExp(`(-?\\d+)\\.(\\d{${n}})(\\d)`);
		strNum.replace(reg, (_$0, $integer, $decimal, $token) => {
			// console.log(`字符串:${strNum}, 整数：${$integer},小数：${$decimal},关键数：${$token}`);
			// 五入
			if (+$token >= 5) {
				// result = `${$integer}.${+$decimal + 1}`;
				result = (+num).toFixed(2);
			} else { // 四舍
				result = `${$integer}.${$decimal}`;
			}
			return '';
		});
		if (isNaN(+result)) {
			result = '';
		}
		return result;
	};

	/** 
	 * 数字转换字符串 1234567890 => 1,234,567,890 
	 * @param {Number} num 要转换的数字
	 * @param {String} prefix 前缀
	 * @param {Number} n 小数保留部分
	 * @returns {String}
	 */
	static moneyFormat = (num, prefix = '￥', n = 2) => {
		const arrNum = num.toFixed(n).split('.');
		const integer = arrNum[0];
		const decimal = arrNum[1] ? '.' + arrNum[1] : '';
		const integerRes = integer.replace(/(\d)(?=(\d{3})+$)/g, '$1,');
		return `${prefix}${integerRes}${decimal}`;
	}

	/** 
	 * 字符串转换数字 1,234,567,890 => 1234567890
	 *  @param {String} str 要转换的字符串
	 * @returns {Number}
	 *  */
	static moneyToNumber = (str) => {
		return +str.replace(/,/g, '') || 0;
	}

	/** 
	 * 数字范围 
	 * @param {Number} val
	 * @param {Number} max
	 * @param {Number} min
	 * @returns {Number}
	 * */
	static rangeNumber = (val, max, min) => {
		if (val > max) {
			return max;
		}
		if (val < min) {
			return min;
		}
		return val
	}

	/** 
	 * 啥也不做
	 * @param {any} 
	 *  */
	static noop = (...args) => {
		if (+new Date() === 1) {
			console.log(args);
		}
	}
	/** 
	 * 啥也不做
	 * @param {any} 
	 *  */
	static doNothing = Utils.noop;

}